package db;

import java.io.IOException;
import java.sql.SQLException;

import core.exceptions.DBAccessException;
import db.queries.AuthorQueries;
import db.queries.BookCommentQueries;
import db.queries.BookQueries;
import db.queries.CategoryQueries;
import db.queries.CityQueries;
import db.queries.CountryQueries;
import db.queries.LoanQueries;
import db.queries.NewsFeedQueries;
import db.queries.PublisherQueries;
import db.queries.UserCommentQueries;
import db.queries.UserQueries;

public class DBAccessEngine {

	private static AuthorQueries authorQueries = null;
	private static BookCommentQueries bookCommentQueries = null;
	private static BookQueries bookQueries = null;
	private static CategoryQueries categoryQueries = null;
	private static CityQueries cityQueries = null;
	private static CountryQueries countryQueries = null;
	private static LoanQueries loanQueries = null;
	private static PublisherQueries publisherQueries = null;
	private static UserCommentQueries userCommentQueries = null;
	private static UserQueries userQueries = null;
	
	private static NewsFeedQueries newsFeedQueries = null;
	
	public synchronized static IDBAccess<?> Author() {
		if (authorQueries == null) {
			authorQueries = new AuthorQueries();
		}
		return authorQueries;
	}

	public synchronized static IDBAccess<?> BookComment() {
		if (bookCommentQueries == null) {
			bookCommentQueries = new BookCommentQueries();
		}
		return bookCommentQueries;
	}

	public synchronized static IDBAccess<?> Book() {
		if (bookQueries == null) {
			bookQueries = new BookQueries();
		}
		return bookQueries;
	}

	public synchronized static IDBAccess<?> Category() {
		if (categoryQueries == null) {
			categoryQueries = new CategoryQueries();
		}
		return categoryQueries;
	}

	public synchronized static IDBAccess<?> City() {
		if (cityQueries == null) {
			cityQueries = new CityQueries();
		}
		return cityQueries;
	}
	
	public synchronized static IDBAccess<?> Country() {
		if (countryQueries == null) {
			countryQueries = new CountryQueries();
		}
		return countryQueries;
	}

	public synchronized static IDBAccess<?> BookLoan() {
		if (loanQueries == null) {
			loanQueries = new LoanQueries();
		}
		return loanQueries;
	}

	public synchronized static IDBAccess<?> Publisher() {
		if (publisherQueries == null) {
			publisherQueries = new PublisherQueries();
		}
		return userQueries;
	}

	public synchronized static IDBAccess<?> UserComment() {
		if (userCommentQueries == null) {
			userCommentQueries = new UserCommentQueries();
		}
		return userCommentQueries;
	}

	public synchronized static IDBAccess<?> User() {
		if (userQueries == null) {
			userQueries = new UserQueries();
		}
		return userQueries;
	}
	
	public synchronized static IDBQuery<?> NewsFeed() {
		if (newsFeedQueries == null) {
			newsFeedQueries = new NewsFeedQueries();
		}
		return newsFeedQueries;
	}
	
	public synchronized static void constructDatabase(IConstructDBProgress progress) throws DBAccessException {
		try {
			
			DBHandler handler = new DBHandler();
			
			if (progress != null)
				progress.storingData("Initalizing Database, building from scratch..");
			
			handler.initializeDB();
			
			if (progress != null) {
				//we give building database 15% of progress, note we start at 50% (after parser)
				progress.initDBFinished(65);
			}

			handler.constructDB(progress);
			
		} catch (SQLException e) {
			throw new DBAccessException("Could not construct Database - unknown error has occured.", e);
		} catch (IOException e) {
			throw new DBAccessException("Could not construct Database - unknown error has occured.", e);
		}
	}
	
	public synchronized static void establishConnectionPool() throws Exception {
		//creates the static connection pool:
		DBHandler.openConnectionPool();
	}
}
